//******************************************************************
//******************************************************************
//**********          ANts Peer To Peer Sources        *************
//
// ANts P2P realizes a third generation P2P net. It protects your
// privacy while you are connected and makes you not trackable, hiding
// your identity (ip) and crypting everything you are sending/receiving
// from others.

// Copyright (C) 2004  Roberto Rossi

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

package ants.p2p.gui;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;

import ants.p2p.security.*;
import ants.p2p.utils.addresses.*;
import ants.p2p.utils.indexer.*;
import ants.p2p.*;
import ants.p2p.filesharing.*;

import org.apache.log4j.*;

public class FrameAnt extends JFrame {
  static FrameAnt instance;
  GuiAnt ga;
  public static int WIDTH = 600;
  public static int HEIGHT = 600;

  static boolean isReady = false;

  static String logFileName = WarriorAnt.workingPath + "Log.properties";

  static{
    File log = new File(FrameAnt.logFileName);
    if(log.exists()){
      PropertyConfigurator.configure(FrameAnt.logFileName);
    }
    else {
      BasicConfigurator.configure();
    }

    FrameAnt.checkWorkingPath();
  }

  static Logger _logger = Logger.getLogger(FrameAnt.class.getName());

  FrameAnt(String title) {
    super(title);
    instance = this;
    try {
      jbInit();
      isReady = true;
    }
    catch(Exception e) {
      _logger.error("",e);
    }
  }

  public GuiAnt getGuiAnt(){
    return ga;
  }

  public static FrameAnt getInstance(String title){
    if(instance == null){
      return instance = new FrameAnt(title);
    }else{
      return instance;
    }
  }

  public static boolean isReady() {
    return isReady;
  }

  public static void checkWorkingPath(){
    File cpf = new File(WarriorAnt.workingPath);
    if(cpf.exists() && !cpf.isDirectory()){
      cpf.delete();
      cpf.mkdir();
    }else if(!cpf.exists()){
      cpf.mkdir();
    }
  }

  public static void main(String args[]){
    _logger.info("Running VM: " + System.getProperty("java.version"));
    _logger.info("Running DIR: " + System.getProperty("java.home"));
    try{
      _logger.info("Checking cipher..............");
      Cipher cipher = Cipher.getInstance(EndpointSecurityManager.cipher);
      _logger.info("Cipher OK");
      _logger.info("Checking key size............");
      byte[] key = new byte[EndpointSecurityManager.cipherKeySize];
      SecretKeySpec secKey = new SecretKeySpec(key,
                                               EndpointSecurityManager.cipher);
      cipher.init(Cipher.ENCRYPT_MODE, secKey);
      _logger.info("Key size OK");
    }catch(Exception e){
      _logger.error("Some features needed by ANts are not supported by current VM",e);
    }
    _logger.info("Loading static settings......");
    SettingsAntPanel.loadStaticSettings();
    SettingsAntPanel.setLookAndFeel();
    _logger.info("Setting language.............");
    ji.JI.setCurrentLanguage(SettingsAntPanel.currentLanguage);
    _logger.info("Initializing ANTs............");
    FrameAnt fa = FrameAnt.getInstance("Ants P2P - version " +
                                       WarriorAnt.getVersion() + " - Protocol: " + WarriorAnt.getProtocolVersion());
    _logger.info("Setting look & feel...");
    SettingsAntPanel.setLookAndFeel(fa);
    _logger.info("Loading ipFilter.dat.........");
    InetAddressWatchdog.getInstance().loadFilterFile(WarriorAnt.workingPath+"ipFilter.dat");
    _logger.info("Showing window...");
    Logger.getRootLogger().setLevel(Level.OFF);
    fa.show();
    fa.validateTree();
  }

  public FrameAnt() {
    try {
      jbInit();
      isReady = true;
    }
    catch(Exception e) {
      _logger.error("",e);
    }
  }

  private void jbInit() throws Exception {
    this.setResizable(true);
    this.addComponentListener(new FrameAnt_this_componentAdapter(this));
    this.addWindowListener(new FrameAnt_this_windowAdapter(this));
    ga = new GuiAnt();
    this.getContentPane().add(ga);

    Image ico = null;
    if(this.ga.animationPanel != null){
      ico = this.ga.animationPanel.getIcon();
    }

    if(ico!=null){
      this.setIcon(ico);
    }

    if(this.ga.sap.autoStartANts()){
      _logger.info("Autostart enabled: running ANts");
      final SwingWorker worker = new SwingWorker() {
        public Object construct() {
          ga.cap.startANts();
          return null;
        }
      };
      worker.start();
    }

    reshape(100,100,650,550);
  }

  public void setIcon(Image ico){
    if(ico!=null){
      try{
        this.setIconImage(ico);
      }catch(Exception e){}
    }
  }

  void this_windowClosing(WindowEvent e) {
    int confirm = JOptionPane.showConfirmDialog(this,
        ji.JI.i("Do you really want to exit?"),
        ji.JI.i("Really?"),
        JOptionPane.OK_CANCEL_OPTION);
    if (confirm == JOptionPane.CANCEL_OPTION) {
      this.setVisible(true);
      return;
    }
    JFrame waitingFrame = this.showWorkingFrame();
    if(this.ga.cap.warriorAnt != null){
      this.ga.cap.warriorAnt.disconnectWarrior();
    }
    if (this.ga.cap.connectionManager != null) {
      this.ga.cap.connectionManager.stop();
      this.ga.cap.connectionManager = null;
    }
    if (this.ga.cap.ircBot != null) {
      this.ga.cap.ircBot.disconnect();
    }
    if (BackgroundEngine.getInstance() != null){
      BackgroundEngine.getInstance().setPriority(Thread.NORM_PRIORITY);
      BackgroundEngine.getInstance().terminate(true);
    }
    waitingFrame.setVisible(false);
    System.exit(0);
  }

  void this_componentResized(ComponentEvent e) {
    this.ga.setPreferredSize(this.getContentPane().getSize());
    this.ga.setSize(this.getContentPane().getSize());
  }

  private JFrame showWorkingFrame(){
    final JFrame connectionDialog = new JFrame("ANts");
    connectionDialog.getContentPane().setLayout(new FlowLayout(FlowLayout.
        CENTER));
    connectionDialog.getContentPane().add(new JLabel(
        "ANts is cleaning up. Please wait..."));
    JButton confirmConnection = new JButton("Force Exit");
    confirmConnection.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        System.exit(0);
      }
    });
    connectionDialog.getContentPane().add(confirmConnection);
    connectionDialog.pack();
    connectionDialog.setLocation(300, 300);
    connectionDialog.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e){
          System.exit(0);
        }
    });
    SettingsAntPanel.setLookAndFeel(connectionDialog);
    connectionDialog.setVisible(true);
    return connectionDialog;
  }
}

class FrameAnt_this_windowAdapter extends java.awt.event.WindowAdapter {
  FrameAnt adaptee;

  FrameAnt_this_windowAdapter(FrameAnt adaptee) {
    this.adaptee = adaptee;
  }
  public void windowClosing(WindowEvent e) {
    final WindowEvent event = e;
    final SwingWorker worker = new SwingWorker() {
      public Object construct() {
        adaptee.this_windowClosing(event);
        return null;
      }
    };
    worker.start();
  }
}

class FrameAnt_this_componentAdapter extends java.awt.event.ComponentAdapter {
  FrameAnt adaptee;

  FrameAnt_this_componentAdapter(FrameAnt adaptee) {
    this.adaptee = adaptee;
  }
  public void componentResized(ComponentEvent e) {
    adaptee.this_componentResized(e);
  }
}
